Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

make Child::try_wait return io::Result<Option<ExitStatus>> #39512

Merged
merged 1 commit into from
Feb 8, 2017

Conversation

oconnor663
Copy link
Contributor

@oconnor663 oconnor663 commented Feb 3, 2017

This is much nicer for callers who want to short-circuit real I/O errors
with ?, because they can write this

if let Some(status) = foo.try_wait()? {
    ...
} else {
    ...
}

instead of this

match foo.try_wait() {
    Ok(status) => {
        ...
    }
    Err(err) if err.kind() == io::ErrorKind::WouldBlock => {
        ...
    }
    Err(err) => return Err(err),
}

The original design of try_wait was patterned after the Read and
Write traits, which support both blocking and non-blocking
implementations in a single API. But since try_wait is never blocking,
it makes sense to optimize for the non-blocking case.

Tracking issue: #38903

@rust-highfive
Copy link
Collaborator

r? @aturon

(rust_highfive has picked a reviewer for you, use r? to override)

@oconnor663
Copy link
Contributor Author

I probably should've written r? @alexcrichton, since this is coming from #38903.

@rust-highfive rust-highfive assigned alexcrichton and unassigned aturon Feb 3, 2017
@alexcrichton
Copy link
Member

Looks good to me, thanks @oconnor663!

@rust-lang/libs any thoughts about this change?

@nagisa
Copy link
Member

nagisa commented Feb 4, 2017

Seems to be inconsistent with how pretty much every other non-blocking operation is handled.

@alexcrichton
Copy link
Member

@nagisa can you elaborate some more? I think a good point is made that read and write are special cases because it's the same API for both blocking and nonblocking, so our hands are force there. Here, however, it's an explicit API and the examples I think are more ergonomic using Option.

What other blocking/nonblocking APIs do we have?

@nagisa
Copy link
Member

nagisa commented Feb 4, 2017

Mutex::try_lock comes to mind, and I could’ve sworn we had more; but I couldn’t find any.

@oconnor663
Copy link
Contributor Author

[added fixes for the try-wait.rs tests, and rebased]

The API currently in master tries to be consistent with Read/Write. I think if we wanted to be maximally consistent with try_lock, we might have an error enum like this:

pub enum TryWaitError {
    Io(std::io::Error),
    WouldBlock,
}

So we might end up with some inconsistency either way? Though maybe that TryWaitError concept doesn't count as a reasonable option, since the io::Error can (and currently does) represent WouldBlock by itself?

My goal here was to make the non-blocking case as nice as possible, by making it a good option to just do try_wait()? if you're already short-circuiting on IO errors. I think by that logic, I wish try_lock had done something similar with Result<Option<MutexGuard>, PoisonError>. Then callers who just want to propagate panics (most of them?) could've done a similar try_lock().unwrap() instead of needing a full match. Do other folks share the "that would've been nice" opinion, or are there benefits to the TryLockError enum that I'm missing?

@oconnor663
Copy link
Contributor Author

oconnor663 commented Feb 5, 2017

Oh and is this the right thing to do to run that test locally right now?

./x.py test src/test/run-pass --test-args try-wait

I found that in https://github.com/rust-lang/rust/blob/master/src/bootstrap/README.md, and it seems to work.

@alexcrichton
Copy link
Member

@oconnor663 looks like the doctest may be failing?

@alexcrichton
Copy link
Member

Ok I'm gonna go ahead an r+, but we can also revisit this signature before stabilization!

@bors: r+

@bors
Copy link
Contributor

bors commented Feb 6, 2017

📌 Commit bd57742 has been approved by alexcrichton

@frewsxcv
Copy link
Member

frewsxcv commented Feb 7, 2017

This is much nicer for callers who want to short-circuit real I/O errors
with `?`, because they can write this

    if let Some(status) = foo.try_wait()? {
        ...
    } else {
        ...
    }

instead of this

    match foo.try_wait() {
        Ok(status) => {
            ...
        }
        Err(err) if err.kind() == io::ErrorKind::WouldBlock => {
            ...
        }
        Err(err) => return Err(err),
    }

The original design of `try_wait` was patterned after the `Read` and
`Write` traits, which support both blocking and non-blocking
implementations in a single API. But since `try_wait` is never blocking,
it makes sense to optimize for the non-blocking case.

Tracking issue: rust-lang#38903
@oconnor663
Copy link
Contributor Author

Rebased and fixed the Windows break (hopefully).

@alexcrichton
Copy link
Member

@bors: r+

@bors
Copy link
Contributor

bors commented Feb 7, 2017

📌 Commit 2a345bb has been approved by alexcrichton

frewsxcv added a commit to frewsxcv/rust that referenced this pull request Feb 8, 2017
make Child::try_wait return io::Result<Option<ExitStatus>>

This is much nicer for callers who want to short-circuit real I/O errors
with `?`, because they can write this

    if let Some(status) = foo.try_wait()? {
        ...
    } else {
        ...
    }

instead of this

    match foo.try_wait() {
        Ok(status) => {
            ...
        }
        Err(err) if err.kind() == io::ErrorKind::WouldBlock => {
            ...
        }
        Err(err) => return Err(err),
    }

The original design of `try_wait` was patterned after the `Read` and
`Write` traits, which support both blocking and non-blocking
implementations in a single API. But since `try_wait` is never blocking,
it makes sense to optimize for the non-blocking case.

Tracking issue: rust-lang#38903
frewsxcv added a commit to frewsxcv/rust that referenced this pull request Feb 8, 2017
make Child::try_wait return io::Result<Option<ExitStatus>>

This is much nicer for callers who want to short-circuit real I/O errors
with `?`, because they can write this

    if let Some(status) = foo.try_wait()? {
        ...
    } else {
        ...
    }

instead of this

    match foo.try_wait() {
        Ok(status) => {
            ...
        }
        Err(err) if err.kind() == io::ErrorKind::WouldBlock => {
            ...
        }
        Err(err) => return Err(err),
    }

The original design of `try_wait` was patterned after the `Read` and
`Write` traits, which support both blocking and non-blocking
implementations in a single API. But since `try_wait` is never blocking,
it makes sense to optimize for the non-blocking case.

Tracking issue: rust-lang#38903
frewsxcv added a commit to frewsxcv/rust that referenced this pull request Feb 8, 2017
make Child::try_wait return io::Result<Option<ExitStatus>>

This is much nicer for callers who want to short-circuit real I/O errors
with `?`, because they can write this

    if let Some(status) = foo.try_wait()? {
        ...
    } else {
        ...
    }

instead of this

    match foo.try_wait() {
        Ok(status) => {
            ...
        }
        Err(err) if err.kind() == io::ErrorKind::WouldBlock => {
            ...
        }
        Err(err) => return Err(err),
    }

The original design of `try_wait` was patterned after the `Read` and
`Write` traits, which support both blocking and non-blocking
implementations in a single API. But since `try_wait` is never blocking,
it makes sense to optimize for the non-blocking case.

Tracking issue: rust-lang#38903
bors added a commit that referenced this pull request Feb 8, 2017
Rollup of 11 pull requests

- Successful merges: #39462, #39512, #39529, #39557, #39561, #39582, #39583, #39597, #39622, #39624, #39630
- Failed merges:
@bors bors merged commit 2a345bb into rust-lang:master Feb 8, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants